using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
//using MyCommons;
using System.Windows.Forms.DataVisualization.Charting;

namespace SPC.Chart
{

    public partial class CtrlChart : UserControl
    {       
        bool enableAreaLines=false;//显示分区线
        bool markUnormals=false;//标识异常点
        bool controlChart = false;//缺省为分析用控制图，有用户指定的ucl和lcl才可启用控制用控制图
        public bool MarkUnormals  {  set { markUnormals = value; }  }       
        int digitals = 3;
        public bool EnableAreaLines
        {
            set
            {
                enableAreaLines = value;
                if (enableAreaLines) ShowAreaLines();
                else RemoveAreaLines();
            }
        }
        public int Digitals
        {
            set { digitals = value; }
        }
        public bool ControlChart
        {
            set
            {
                controlChart = value;
                chart.Titles[0].Text = controlChart ? "CONTROL CHART" : "ANALYSIS CHART";
            }
        }
        List<SUnormals> unormList = new List<SUnormals>();
        List<SCtrlDiagram> diagramList = new List<SCtrlDiagram>();
        
        
        
    public CtrlChart()
        {
            InitializeComponent();
           
        }
       
       public void LoadDiagrams(SCtrlDiagram[] diagrams)
        {
            diagramList.Clear();
            chart.Series.Clear();
            chart.ChartAreas.Clear();
            for (int i = 0; i < diagrams.Length; i++)
            {
                InitialDiagram(diagrams[i]);
                DrawDataPoints(diagrams[i]);
            }
            DrawControlLine();
            chart.Legends.Clear();
        }
        public void LoadDiagram(SCtrlDiagram diagram1)
        {            //数据点的serie用图名来命名，方便后面查找
            diagramList.Clear();
            chart.Series.Clear();
            chart.ChartAreas.Clear();
            InitialDiagram(diagram1);
            chart.Legends.Clear();
            DrawControlLine();
            DrawDataPoints(diagram1);
        }
        public void LoadDiagram(SCtrlDiagram diagram1, SCtrlDiagram diagram2)
        {
            diagramList.Clear();
            chart.Series.Clear();
            chart.ChartAreas.Clear();
            InitialDiagram(diagram1);
            InitialDiagram(diagram2);
            chart.Legends.Clear();
            DrawControlLine();
            DrawDataPoints(diagram1);
            DrawDataPoints(diagram2);

        }
        private void DrawDataPoints(SCtrlDiagram diagram)
        {
            for (int i = 0; i < diagram.points.Length; i++)
            {
                chart.Series[diagram.diagramName].Points.AddXY(i + 1, diagram.points[i]);
            }
        }
        private void InitialDiagram(SCtrlDiagram diagram)
        {
            diagramList.Add(diagram);
            string diagName = diagram.diagramName;
            chart.ChartAreas.Add(diagName);
            chart.ChartAreas[diagName].AxisY.Title = diagName.ToUpper();
            //chart.ChartAreas[diagName].AxisY.Name = diagName;
            chart.ChartAreas[diagName].AxisX.Minimum = 1;
            chart.ChartAreas[diagName].AxisX.Maximum = diagram.points.Length;
            double lcl,ucl;
                  
            if(diagram.lcls.Length>0)
            {
                lcl = diagram.lcls.Min();
                ucl = diagram.ucls.Max();
                lcl = Math.Round(lcl - 0.5 * (ucl - lcl), digitals);
                chart.ChartAreas[diagName].AxisY.Minimum = lcl;
            }
            else
            {
                lcl = Math.Round(diagram.lcl - 0.5 * (diagram.ucl - diagram.lcl), digitals);
                chart.ChartAreas[diagName].AxisY.Minimum = lcl;
            }
            if(diagram.ucls.Length>0)
            {
                lcl = diagram.lcls.Min();
                ucl = diagram.ucls.Max();
                ucl = Math.Round(ucl + 0.5 * (ucl - lcl), digitals);
                chart.ChartAreas[diagName].AxisY.Maximum = ucl;
            }
            else
            {
                ucl = Math.Round(diagram.ucl + 0.5 * (diagram.ucl - diagram.lcl), digitals);
                chart.ChartAreas[diagName].AxisY.Maximum = ucl;
            }
            

            chart.ChartAreas[diagName].BorderWidth = 1;
            chart.ChartAreas[diagName].BorderColor = Color.Black;
            chart.ChartAreas[diagName].BorderDashStyle = ChartDashStyle.Solid;
            chart.ChartAreas[diagName].AxisY.MajorGrid.Enabled = false;
            chart.ChartAreas[diagName].AxisX.MajorGrid.Enabled = false;

            string dCount = diagramList.Count.ToString();
            chart.Series.Add("UCL"+ dCount);
            chart.Series.Add("CL" + dCount);
            chart.Series.Add("LCL" + dCount);
            chart.Series["UCL" + dCount].Color = Color.Red;
            chart.Series["UCL" + dCount].ChartType = SeriesChartType.StepLine;
            chart.Series["UCL" + dCount].BorderDashStyle = ChartDashStyle.Dash;
            chart.Series["UCL" + dCount].IsValueShownAsLabel = true;
            chart.Series["CL" + dCount].Color = Color.Blue;
            chart.Series["CL" + dCount].ChartType = SeriesChartType.Line;
            chart.Series["CL" + dCount].IsValueShownAsLabel = true;
            chart.Series["LCL" + dCount].Color = Color.Red;
            chart.Series["LCL" + dCount].ChartType = SeriesChartType.StepLine;
            chart.Series["LCL" + dCount].BorderDashStyle = ChartDashStyle.Dash;
            chart.Series["LCL" + dCount].IsValueShownAsLabel = true;

            chart.Series.Add(diagName);
            chart.Series[diagName].Color = Color.Blue;
            chart.Series["UCL" + dCount].ChartArea = diagName;
            chart.Series["CL" + dCount].ChartArea = diagName;
            chart.Series["LCL" + dCount].ChartArea = diagName;
            chart.Series[diagName].ChartArea = diagName;

            chart.Series[diagName].ChartType = SeriesChartType.Line;
            chart.Series[diagName].MarkerStyle = MarkerStyle.Circle;
            chart.Series[diagName].MarkerSize = 8;
            
        }
        private void DrawControlLine()
        {//绘制控制线
            for (int i = 0; i < diagramList.Count; i++)
            {
                double value = Math.Round(diagramList[i].cl, digitals);
                chart.Series["CL" + (i + 1).ToString()].Points.AddXY(1, value);
                chart.Series["CL" + (i + 1).ToString()].Points.AddXY(diagramList[i].points.Length, value);
                if (diagramList[i].ucls.Length > 0)
                {
                    for (int k = 0; k < diagramList[i].ucls.Length; k++)
                    {
                        value = Math.Round(diagramList[i].ucls[k], digitals);
                        chart.Series["UCL" + (i + 1).ToString()].Points.AddY(value);
                    }                    
                }
                else
                {
                    value = Math.Round(diagramList[i].ucl, digitals);
                    chart.Series["UCL" + (i + 1).ToString()].Points.AddXY(1, value);
                    chart.Series["UCL" + (i + 1).ToString()].Points.AddXY(diagramList[i].points.Length, value);
                }
                if (diagramList[i].lcls.Length >  0)
                {
                    for (int k = 0; k < diagramList[i].lcls.Length; k++)
                    {
                        value = Math.Round(diagramList[i].lcls[k], digitals);
                        chart.Series["LCL" + (i + 1).ToString()].Points.AddY(value);
                    }
                }
                else
                {
                    value = Math.Round(diagramList[i].lcl, digitals);
                    chart.Series["LCL" + (i + 1).ToString()].Points.AddXY(1, value);
                    chart.Series["LCL" + (i + 1).ToString()].Points.AddXY(diagramList[i].points.Length, value);
                }               
                
            }
        }
        private void ShowAreaLines()
        {   
            double[] areaLines = new double[4];
            for (int i = 0; i < diagramList.Count; i++)
            {
                double sigma = (diagramList[i].ucl - diagramList[i].lcl) / 6;
                areaLines[0] = diagramList[i].cl - 2 * sigma;
                areaLines[1] = diagramList[i].cl - 1 * sigma;
                areaLines[2] = diagramList[i].cl + 1 * sigma;
                areaLines[3] = diagramList[i].cl + 2 * sigma;
                for (int k = 0; k < areaLines.Length; k++)
                {
                    chart.Series.Add("AreaLine" + k.ToString() + i.ToString());
                    chart.Series[chart.Series.Count - 1].Color = Color.Magenta;
                    chart.Series[chart.Series.Count - 1].ChartType = SeriesChartType.Line;
                    chart.Series[chart.Series.Count - 1].IsValueShownAsLabel = true;
                    chart.Series[chart.Series.Count - 1].IsVisibleInLegend = false;
                    chart.Series[chart.Series.Count - 1].ChartArea = chart.ChartAreas[i].Name;
                    chart.Series[chart.Series.Count - 1].Points.AddXY(1, areaLines[k]);
                    chart.Series[chart.Series.Count - 1].Points.AddXY(diagramList[i].points.Length, areaLines[k]);
                }
            }
            
        }
        private void RemoveAreaLines()
        {
            int count = chart.Series.Count - diagramList.Count * 4;
            //无分区线时，标准曲线为每个图4条(UCL,CL,LCL,DATA)
            if(count>0)
            {
                for (int i = 0; i < count; i++)
                {//删除最后一条
                    chart.Series.RemoveAt(chart.Series.Count - 1);
                }
            }
            
        }
        public void ShowUnormals(List<SUnormals> unormList, bool includeAllCharts = false)
        {            
            foreach (SCtrlDiagram g in diagramList)
            {
                if(includeAllCharts)
                {
                    ShowUnormals(unormList, g.diagramName);
                }
                else
                {//判异准则仅针对X值或均值
                    if (g.diagramName == DiagramName.X || g.diagramName == DiagramName.xbar)
                        ShowUnormals(unormList, g.diagramName);
                }
            }
        }
        private void ShowUnormals(List<SUnormals> unormList,string diagramName)
        {            
            if (markUnormals)
            {
                for (int n = 0; n < chart.Series.Count; n++)
                {
                    if (chart.Series[n].Name == diagramName)
                    {
                        for (int k = 0; k < unormList.Count; k++)
                        {
                            chart.Series[n].Points[unormList[k].pointIndex].Color = Color.Red;
                        }
                    }
                }               
            }
            else
            {
                for (int n = 0; n < chart.Series.Count; n++)
                {
                    for (int i = 0; i < chart.ChartAreas.Count; i++)
                    {
                        if (chart.Series[n].Name == chart.ChartAreas[i].Name)
                        {
                            chart.Series[n].Points.Clear();
                            for (int k = 0; k < diagramList[i].points.Length; k++)
                            {
                                chart.Series[n].Points.AddXY(k + 1, diagramList[i].points[k]);
                            }
                        }
                    }

                }
            }
        }

    }
    
   
}
